using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.Collections.Generic;

public class Credit : AccountItem
{
    private int creditId;
    private int accountId;
    private CreditDirection direction;
    private string reference;
    private string details;

    public int CreditId
    {
        get { return creditId; }
        set { creditId = value; }
    }

    public int AccountId
    {
        get { return accountId; }
        set { accountId = value; }
    }

    public CreditDirection Direction
    {
        get { return direction; }
        set { direction = value; }
    }

    public string Reference
    {
        get { return reference; }
        set { reference = value; }
    }

    public string Details
    {
        get { return details; }
        set { details = value; }
    }

    protected Credit() { }

    protected Credit(
        int creditId,
        int accountId,
        CreditDirection direction,
        decimal amount,
        string reference,
        string details,
        DateTime creditDate,
        DateTime createDate,
        DateTime updateDate)
        : base(creditDate, createDate, updateDate, amount)
    {
        this.creditId = creditId;
        this.accountId = accountId;
        this.direction = direction;
        this.reference = reference;
        this.details = details;
    }

    protected Credit(
        int creditId,
        int accountId,
        CreditDirection direction,
        decimal amount,
        string reference,
        string details,
        DateTime creditDate,
        DateTime createDate,
        DateTime updateDate,
        string accountCode,
        string accountTitle)
        : this(
        creditId,
        accountId,
        direction,
        amount,
        reference,
        details,
        creditDate,
        createDate,
        updateDate)
    {
        this.AccountCode = accountCode;
        this.AccountTitle = accountTitle;
    }

    public static Credit Create(
        CreditDirection direction, 
        decimal amount, 
        DateTime creditDate, 
        string details, 
        string reference, 
        int accountId)
    {
        int creditId;
        using (SqlConnection connection = new SqlConnection(Settings.ConnectionStrings.AccountsDatabase))
        {
            SqlCommand command = new SqlCommand("CreditCreate", connection);
            command.CommandType = CommandType.StoredProcedure;

            if (direction == CreditDirection.Recieve)
            {
                // Invert amount if payment has been recieved.
                amount *= -1;
            }

            command.Parameters.AddWithValue("accountId", accountId);
            command.Parameters.AddWithValue("reference", reference);
            command.Parameters.AddWithValue("details", details);
            command.Parameters.AddWithValue("creditDate", creditDate);
            command.Parameters.AddWithValue("amount", amount);
            command.Parameters.Add("creditId", SqlDbType.Int).Direction = ParameterDirection.Output;

            connection.Open();
            command.ExecuteNonQuery();
            connection.Close();

            creditId = (int)command.Parameters["creditId"].Value;
        }

        return new Credit(
            creditId, accountId, direction, amount, reference, details,
            creditDate, DateTime.Now, DateTime.Now);
    }

    public static Credit FromReader(SqlDataReader reader)
    {
        decimal amount = (decimal)reader["Amount"];
        CreditDirection direction = (amount < 0) ? CreditDirection.Recieve : CreditDirection.Send;
        if (direction == CreditDirection.Recieve)
        {
            // Invert negative recieve value.
            amount *= -1;
        }

        Credit credit = new Credit(
            (int)reader["CreditId"],
            (int)reader["AccountId"],
            direction, amount,
            (string)reader["Reference"],
            (string)reader["Details"],
            (DateTime)reader["CreditDate"],
            (DateTime)reader["CreateDate"],
            (DateTime)reader["UpdateDate"],
            (string)reader["AccountCode"],
            (string)reader["AccountTitle"]);

        return credit;
    }

    public static List<Credit> Fetch()
    {
        List<Credit> creditList = new List<Credit>();
        using (SqlConnection connection = new SqlConnection(Settings.ConnectionStrings.AccountsDatabase))
        {
            SqlCommand command = new SqlCommand("CreditFetch", connection);
            command.CommandType = CommandType.StoredProcedure;

            connection.Open();
            SqlDataReader reader = command.ExecuteReader();
            while (reader.Read())
            {
                creditList.Add(Credit.FromReader(reader));
            }
            connection.Close();
        }
        return creditList;
    }

    public static List<Credit> Fetch(int accountId)
    {
        List<Credit> creditList = new List<Credit>();
        using (SqlConnection connection = new SqlConnection(Settings.ConnectionStrings.AccountsDatabase))
        {
            SqlCommand command = new SqlCommand("CreditFetchByAccountId", connection);
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.AddWithValue("accountId", accountId);

            connection.Open();
            SqlDataReader reader = command.ExecuteReader();
            while (reader.Read())
            {
                creditList.Add(FromReader(reader));
            }
            connection.Close();
        }
        return creditList;
    }
}
